﻿/**
* @description  Class that alters multiple values over time, passing altered values to a specified function.
*/
package com.foed.animation {

	import flash.events.TimerEvent;
	import flash.utils.Timer;

	import com.foed.animation.easing.Linear;
	import com.foed.events.TweenEvent;

	public class TweenRunner extends Animator {
	
		private var _startValue:Object;
		private var _destValue:Object;
		private var _changeValue:Object;
		private var _currentValue:Object;
		private var _time:Number;
		private var _easeFunction:Function;
		private var _totalInts:uint;

		/**
		* @description  Constructor.
		*
		* @param  pStartValue  The value of the property at the start of the tween.
		* @param  pDestValue  The value of the property at the end of the tween.
		* @param  pTime  The number of milliseconds the tween should run.
		* @param  pEaseFunction  The function to use to calculate values during the tween.
		*/
		public function TweenRunner(
			pStartValue:Object,
			pDestValue:Object,
			pTime:Number,
			pEaseFunction:Function=null
		) {
			_startValue = pStartValue;
			_destValue = pDestValue;
			_time = pTime;
			_totalInts = Math.floor(_time/Animator.intervalTime);
			_easeFunction = pEaseFunction||Linear.easeNone;
			_changeValue = {};
			for (var i:String in _startValue) {
				_changeValue[i] = _destValue[i] - _startValue[i];
			}
		}
	
		/**
		* @description  Called by the Timer to change the object's properties over the course of the tween.
		*
		* @param  pEvent  The event fired by the Timer.
		*/
		private function runTween(pEvent:TimerEvent):void {
			if (_timer.currentCount >= _totalInts) {
				_currentValue = _destValue;
				halt();
				dispatchEvent(new TweenEvent(TweenEvent.CHANGE, this));
				dispatchEvent(new TweenEvent(TweenEvent.END, this));
			} else {
				_currentValue = {};
				for (var i:String in _changeValue) {
					_currentValue[i] = _easeFunction(_timer.currentCount, _startValue[i], _changeValue[i], _totalInts);
				}
				dispatchEvent(new TweenEvent(TweenEvent.CHANGE, this));
			}
		}
	
		/**
		* @description  Starts the animation.
		*/
		override public function start():void {
			_timer = new Timer(Animator.intervalTime, _totalInts);
			_timer.addEventListener(TimerEvent.TIMER, runTween, false, 0, true);
			_timer.start();
			_currentValue = _startValue;
			dispatchEvent(new TweenEvent(TweenEvent.START, this));
			runTween(new TimerEvent(TimerEvent.TIMER));
		}
	
		/**
		* @description  Stops the animation.
		*/
		override public function halt():void {
			_timer.removeEventListener(TimerEvent.TIMER, runTween);
			_timer.stop();
		}

		/**
		* @description  Cleans up any timers that might be running.
		*/
		override public function die():void {
			super.die();
			_startValue = null;
			_destValue = null;
			_easeFunction = null;
			_changeValue = null;
			_currentValue = null;
		}

		/**
		* @description  Returns the current value of the properties being tweened.
		* 
		* @returns  The current values for all of the properties managed by the tween.
		*/
		public function get value():Object {
			return _currentValue;
		}

	}

}